//
// Created by 相开原 on 2022/3/23.
//

#include "data.h"

fruit *head_fruitStored = NULL;
fruit *head_fruitOnShelf = NULL;
purchaseMessage *head_purchaseMessage = NULL;
sellMessage *head_sellMessage = NULL;
account *head_user = NULL;
account *head_VIP = NULL;
//下面建立了四个指向链表尾的指针，用于加速建表
fruit *tail_fruitStored = NULL;
fruit *tail_fruitOnShelf = NULL;
purchaseMessage *tail_purchaseMessage = NULL;
sellMessage *tail_sellMessage = NULL;

struct shop_item shop;
account *current_user = NULL;

//用文件初始化链表，一次运行仅会进行一次
void init() {
    clock_t start_t = clock();  //用于计算数据载入时间
    head_fruitStored = fruit_create();
    head_fruitOnShelf = fruit_create();
    head_purchaseMessage = purchaseMessage_create();
    head_sellMessage = sellMessage_create();
    head_user = account_create();
    head_VIP = account_create();

    read_fruitStored("./data/fruitStored.csv", head_fruitStored);
    read_fruitOnShelf("./data/fruitOnShelf.csv", head_fruitOnShelf);
    read_purchaseMessage("./data/purchaseMessage.csv", head_purchaseMessage);
    read_sellMessage("./data/sellMessage.csv", head_sellMessage);
    read_account("./data/user.dat", head_user);
    read_account("./data/VIP.dat", head_VIP);
    read_shop("./data/shopInfo.dat", &shop);
    clock_t end_t = clock();
    printf("init time: %.2f s\n", (double) (end_t - start_t) / CLOCKS_PER_SEC);
}

void checkPoint(char path_src[]) {
    write_fruitStored(path_src);
    write_fruitOnShelf(path_src);
    write_purchaseMessage(path_src);
    write_sellMessage(path_src);
    write_account(path_src);
    write_shopInfo(path_src);
}

// 需要注意的是，head永远为空（哨兵节点）

// 🔽 =========== 以下为 fruit 部分 =========== 🔽

void read_fruitStored(char *path, fruit *head) {
    if (isFileOK(path)) {
        FILE *fp = fopen(path, "r");
        char temp[256];
        fruit item;
        fgets(temp, 255, fp);   // 跳过第一行
        while (!feof(fp)) {
            fscanf(fp, "%s%s%lf%lf%d%d/%d/%d", item.name, item.type, &item.unitPrice, &item.kilo, &item.lifetime,
                   &item.life.year, &item.life.month, &item.life.day);
            fruit_add(head, item);
        }
        fclose(fp);
    }
}

void read_fruitOnShelf(char *path, fruit *head) {
    if (isFileOK(path)) {
        FILE *fp = fopen(path, "r");
        char temp[256], priceMode[16], level[16];
        fruit item;
        fgets(temp, 255, fp);   // 跳过第一行
        while (!feof(fp)) {
            fscanf(fp, "%s%s%lf%lf%s%s%d/%d/%d%d/%d/%d-%d:%d:%d", item.name, item.type, &item.unitPrice, &item.kilo,
                   priceMode, level, &item.life.year, &item.life.month, &item.life.day,
                   &item.shelfTime.year, &item.shelfTime.month, &item.shelfTime.day,
                   &item.shelfTime.hour, &item.shelfTime.minute, &item.shelfTime.second);
            item.mode = text_to_priceMode(priceMode);
            item.level = text_to_fruitLevel(level);
            fruit_add(head, item);
        }
        fclose(fp);
    }
}

void write_fruitStored(char *path_src) {
    char path[64];
    strcpy(path, path_src);
    strcat(path, "fruitStored.csv");
    FILE *fp = fopen(path, "w");
    fprintf(fp, "名称 品种 单价 数量 保质期 到期时间\n");
    for (fruit *p = head_fruitStored->next; p != NULL; p = p->next) {
        fprintf(fp, "%s %s %.2lf %.2lf %d %d/%d/%d",
                p->name, p->type, p->unitPrice, p->kilo, p->lifetime, p->life.year, p->life.month, p->life.day);
        if (p->next != NULL) fprintf(fp, "\n");
    }
    fclose(fp);
}

void write_fruitOnShelf(char *path_src) {
    char path[64];
    strcpy(path, path_src);
    strcat(path, "fruitOnShelf.csv");
    FILE *fp = fopen(path, "w");
    fprintf(fp, "名称 品种 单价 数量 价格模式 等级 到期时间 上架时间\n");
    for (fruit *p = head_fruitOnShelf->next; p != NULL; p = p->next) {
        fprintf(fp, "%s %s %.2lf %.2lf %s %s %d/%d/%d %d/%d/%d-%d:%d:%d",
                p->name, p->type, p->unitPrice, p->kilo, priceMode_to_text(p->mode), fruitLevel_to_text(p->level),
                p->life.year, p->life.month, p->life.day,
                p->shelfTime.year, p->shelfTime.month, p->shelfTime.day,
                p->shelfTime.hour, p->shelfTime.minute, p->shelfTime.second);
        if (p->next != NULL) fprintf(fp, "\n");
    }
    fclose(fp);
}

fruit *fruit_create() {
    fruit *head = (fruit *) malloc(sizeof(struct data_fruitItem));
    head->name[0] = '\0';
    head->next = NULL;
    return head;
}

void fruit_add(fruit *head, fruit item) {
    fruit *p = (fruit *) malloc(sizeof(struct data_fruitItem));
    *p = item;
    p->next = NULL;

    if (head == head_fruitStored) {
        if (tail_fruitStored == NULL) tail_fruitStored = head_fruitStored;
        tail_fruitStored->next = p;
        tail_fruitStored = tail_fruitStored->next;
    } else if (head == head_fruitOnShelf) {
        if (tail_fruitOnShelf == NULL) tail_fruitOnShelf = head_fruitOnShelf;
        tail_fruitOnShelf->next = p;
        tail_fruitOnShelf = p;
    } else {
        fruit *tail = head;
        while (tail->next != NULL) tail = tail->next;
        tail->next = p;
    }
}

bool fruit_del(fruit *head, fruit *target) {
    fruit *p = head;
    while (p->next != NULL) {
        if (p->next == target) {
            p->next = target->next;
            free(target);
            return true;
        }
        p = p->next;
    }
    puts("⚠️未找到要删除的对象！");
    return false;
}

void fruit_free(fruit *head) {
    fruit *tail = head;
    while (head != NULL) {
        tail = tail->next;
        free(head);
        head = tail;
    }
}

// 🔽 =========== 以下为 purchaseMessage 部分 =========== 🔽

void read_purchaseMessage(char *path, purchaseMessage *head) {
    if (isFileOK(path)) {
        FILE *fp = fopen(path, "r");
        char temp[256];
        purchaseMessage item;
        fgets(temp, 255, fp);   // 跳过第一行
        while (!feof(fp)) {
            fscanf(fp, "%s%s%lf%lf%lf%s%d/%d/%d-%d:%d:%d",
                   item.name, item.type, &item.unitPrice, &item.kilo, &item.totalPrice, item.supplier,
                   &item.purchaseTime.year, &item.purchaseTime.month, &item.purchaseTime.day,
                   &item.purchaseTime.hour, &item.purchaseTime.minute, &item.purchaseTime.second);
            purchaseMessage_add(head, item);
        }
        fclose(fp);
    }
}

void write_purchaseMessage(char *path_src) {
    char path[64];
    strcpy(path, path_src);
    strcat(path, "purchaseMessage.csv");
    FILE *fp = fopen(path, "w");
    fprintf(fp, "名称 品种 单价 数量 总价 进货商 进货时间\n");
    for (purchaseMessage *p = head_purchaseMessage->next; p != NULL; p = p->next) {
        fprintf(fp, "%s %s %.2lf %.2lf %.2lf %s %d/%d/%d-%d:%d:%d",
                p->name, p->type, p->unitPrice, p->kilo, p->totalPrice, p->supplier,
                p->purchaseTime.year, p->purchaseTime.month, p->purchaseTime.day,
                p->purchaseTime.hour, p->purchaseTime.minute, p->purchaseTime.second);
        if (p->next != NULL) fprintf(fp, "\n");
    }
    fclose(fp);
}

purchaseMessage *purchaseMessage_create() {
    purchaseMessage *head = (purchaseMessage *) malloc(sizeof(purchaseMessage));
    head->name[0] = '\0';
    head->next = NULL;
    return head;
}

void purchaseMessage_add(purchaseMessage *head, purchaseMessage item) {
    purchaseMessage *p = (purchaseMessage *) malloc(sizeof(purchaseMessage));
    *p = item;
    p->next = NULL;

    if (head == head_purchaseMessage) {
        if (tail_purchaseMessage == NULL) tail_purchaseMessage = head_purchaseMessage;
        tail_purchaseMessage->next = p;
        tail_purchaseMessage = p;
    } else {
        purchaseMessage *tail = head;
        while (tail->next != NULL) tail = tail->next;
        tail->next = p;
    }
}

bool purchaseMessage_del(purchaseMessage *head, purchaseMessage *target) {
    purchaseMessage *p = head;
    while (p->next != NULL) {
        if (p->next == target) {
            p->next = target->next;
            free(target);
            return true;
        }
        p = p->next;
    }
    puts("⚠️未找到要删除的对象！");
    return false;
}

void purchaseMessage_free(purchaseMessage *head) {
    purchaseMessage *tail = head;
    while (head != NULL) {
        tail = tail->next;
        free(head);
        head = tail;
    }
}

// 🔽 =========== 以下为 sellMessage 部分 =========== 🔽

void read_sellMessage(char *path, sellMessage *head) {
    if (isFileOK(path)) {
        FILE *fp = fopen(path, "r");
        char temp[256];
        fgets(temp, 255, fp);   // 跳过第一行
        while (!feof(fp)) {
            sellMessage item;
            fscanf(fp, "%d%lf%s%d/%d/%d-%d:%d:%d", &item.number, &item.totalPrice, item.customer,
                   &item.sellTime.year, &item.sellTime.month, &item.sellTime.day,
                   &item.sellTime.hour, &item.sellTime.minute, &item.sellTime.second);

            //处理链中链
            item.head = fruit_create();
            for (int i = 0; i < item.number; ++i) {
                char priceMode[16], level[16];
                fruit content;
                fscanf(fp, "%s%s%lf%lf%s%s%d/%d/%d%d/%d/%d-%d:%d:%d",
                       content.name, content.type, &content.unitPrice, &content.kilo,
                       priceMode, level, &content.life.year, &content.life.month, &content.life.day,
                       &content.shelfTime.year, &content.shelfTime.month, &content.shelfTime.day,
                       &content.shelfTime.hour, &content.shelfTime.minute, &content.shelfTime.second);
                content.mode = text_to_priceMode(priceMode);
                content.level = text_to_fruitLevel(level);
                fruit_add(item.head, content);
            }
            sellMessage_add(head, item);
        }
        fclose(fp);
    }
}

void write_sellMessage(char *path_src) {
    char path[64];
    strcpy(path, path_src);
    strcat(path, "sellMessage.csv");
    FILE *fp = fopen(path, "w");
    fprintf(fp, "购买数量 总价 顾客信息 销售时间\n");
    for (sellMessage *p = head_sellMessage->next; p != NULL; p = p->next) {
        fprintf(fp, "%d %.2lf %s %d/%d/%d-%d:%d:%d", p->number, p->totalPrice, p->customer,
                p->sellTime.year, p->sellTime.month, p->sellTime.day,
                p->sellTime.hour, p->sellTime.minute, p->sellTime.second);
        if (p->number != 0) {
            fprintf(fp, "\n");
            for (fruit *q = p->head->next; q != NULL; q = q->next) {
                fprintf(fp, "%s %s %.2lf %.2lf %s %s %d/%d/%d %d/%d/%d-%d:%d:%d",
                        q->name, q->type, q->unitPrice, q->kilo,
                        priceMode_to_text(q->mode), fruitLevel_to_text(q->level),
                        q->life.year, q->life.month, q->life.day,
                        q->shelfTime.year, q->shelfTime.month, q->shelfTime.day,
                        q->shelfTime.hour, q->shelfTime.minute, q->shelfTime.second);
                if (q->next != NULL) fprintf(fp, "\n");
            }
        }
        if (p->next != NULL) fprintf(fp, "\n");
    }
    fclose(fp);
}

sellMessage *sellMessage_create() {
    sellMessage *head = (sellMessage *) malloc(sizeof(sellMessage));
    head->head = NULL;
    head->next = NULL;
    return head;
}

void sellMessage_add(sellMessage *head, sellMessage item) {
    sellMessage *p = (sellMessage *) malloc(sizeof(sellMessage));
    *p = item;
    p->next = NULL;

    if (head == head_sellMessage) {
        if (tail_sellMessage == NULL) tail_sellMessage = head_sellMessage;
        tail_sellMessage->next = p;
        tail_sellMessage = p;
    } else {
        sellMessage *tail = head;
        while (tail->next != NULL) tail = tail->next;
        tail->next = p;
    }
}

bool sellMessage_del(sellMessage *head, sellMessage *target) {
    sellMessage *p = head;
    while (p->next != NULL) {
        if (p->next == target) {
            p->next = target->next;
            fruit_free(target->head);
            free(target);
            return true;
        }
        p = p->next;
    }
    puts("⚠️ 未找到要删除的对象！");
    return false;
}

void sellMessage_free(sellMessage *head) {
    sellMessage *tail = head;
    while (head != NULL) {
        tail = tail->next;
        free(head);
        head = tail;
    }
}

// 🔽 =========== 以下为 account 部分 =========== 🔽

void write_account(char *path_src) {
    char path[64];
    strcpy(path, path_src);
    strcat(path, "user.dat");
    FILE *fp = fopen(path, "w");
    account *p1 = head_user;
    while (p1->next != NULL) {
        p1 = p1->next;
        fprintf(fp, "username = %s\n", p1->username);
        fprintf(fp, "password = %s\n", p1->password);
        fprintf(fp, "addTime = %4d/%02d/%02d\n", p1->addTime.year, p1->addTime.month, p1->addTime.day);
        fprintf(fp, "money = %.2lf\n", p1->money);
        fprintf(fp, "type = %c", p1->type);
        if (p1->next != NULL)
            fprintf(fp, "\n\n");
    }
    fclose(fp);

    strcpy(path, path_src);
    strcat(path, "VIP.dat");
    fp = fopen(path, "w");
    account *p2 = head_VIP;
    while (p2->next != NULL) {
        p2 = p2->next;
        fprintf(fp, "username = %s\n", p2->username);
        fprintf(fp, "password = %s\n", p2->password);
        fprintf(fp, "addTime = %4d/%02d/%02d\n", p2->addTime.year, p2->addTime.month, p2->addTime.day);
        fprintf(fp, "money = %.2lf\n", p2->money);
        fprintf(fp, "type = %c", p2->type);
        if (p2->next != NULL)
            fprintf(fp, "\n\n");
    }
    fclose(fp);
}

void read_account(char *path, account *head) {
    if (isFileOK(path)) {
        FILE *fp = fopen(path, "r");
        while (!feof(fp) && fp != NULL) {
            account temp;
            fscanf(fp, "username = %s\n", temp.username);
            fscanf(fp, "password = %s\n", temp.password);
            fscanf(fp, "addTime = %d/%d/%d\n", &temp.addTime.year, &temp.addTime.month, &temp.addTime.day);
            fscanf(fp, "money = %lf\n", &temp.money);
            fscanf(fp, "type = %c", &temp.type);
            account_add(head, temp);
            if (!feof(fp)) fscanf(fp, "\n\n");
        }
        fclose(fp);
    }
}

account *account_create() {
    account *head = (account *) malloc(sizeof(account));
    head->username[0] = '\0';
    head->next = NULL;
    return head;
}

void account_add(account *head, account item) {
    account *tail = head;
    while (tail->next != NULL) {
        tail = tail->next;
    }
    account *p = (account *) malloc(sizeof(account));
    *p = item;
    tail->next = p;
    p->next = NULL;
}

bool account_del(account *head, account *target) {
    account *p = head;
    while (p->next != NULL) {
        if (p->next == target) {
            p->next = target->next;
            free(target);
            return true;
        }
        p = p->next;
    }
    return false;
}

void account_free(account *head) {
    account *tail = head;
    while (head != NULL) {
        tail = tail->next;
        free(head);
        head = tail;
    }
}

// 🔽 =========== 以下为 shop 部分 =========== 🔽

void read_shop(char *path, struct shop_item *item) {
    if (isFileOK(path)) {
        FILE *fp = fopen(path, "r");
        fscanf(fp, "ShopName = %s\n", item->name);
        fscanf(fp, "StartMoney = %lf\n", &item->startMoney);
        fscanf(fp, "BuildDate = %d/%d/%d\n", &item->buildTime.year, &item->buildTime.month, &item->buildTime.day);
        fscanf(fp, "AutoBackup = %d", &item->autoBackup);
        fclose(fp);
    }
}

void write_shopInfo(char *path_src) {
    char path[64];
    strcpy(path, path_src);
    strcat(path, "shopInfo.dat");
    FILE *fp = fopen(path, "w");
    fprintf(fp, "ShopName = %s\n", shop.name);
    fprintf(fp, "StartMoney = %.2lf\n", shop.startMoney);
    fprintf(fp, "BuildDate = %d/%d/%d\n", shop.buildTime.year, shop.buildTime.month, shop.buildTime.day);
    fprintf(fp, "AutoBackup = %d", shop.autoBackup);
    fclose(fp);
}

// 🔽 =========== 以下为 pointer 部分 =========== 🔽

void pointer_swap(pointer *p1, pointer *p2) {
    pointer temp = *p1;
    *p1 = *p2;
    *p2 = temp;
    pointer *tp = p1->next;
    p1->next = p2->next;
    p2->next = tp;
}

//下为链表快速排序（支持正序/逆序）
pointer *partition(pointer *head, pointer *tail, bool descending) {
    int pivot = head->temp;
    pointer *left = head, *cur = head->next;
    while (cur != NULL && cur != tail) {
        if (descending ? cur->temp > pivot : cur->temp < pivot) {
            left = left->next;
            pointer_swap(cur, left);
        }
        cur = cur->next;
    }
    pointer_swap(left, head);
    return left;
}

void quicksort(pointer *head, pointer *tail, bool descending) {
    if (head == tail || head->next == NULL)
        return;
    pointer *mid = partition(head, tail, descending);
    quicksort(head, mid, descending);
    quicksort(mid->next, tail, descending);
}

void pointer_sort(pointer *head, bool descending) {
    if (head == NULL || head->next == NULL) return;
    quicksort(head->next, NULL, descending);
}

pointer *pointer_create() {
    pointer *head = (pointer *) malloc(sizeof(pointer));
    head->temp = 0;
    head->p_fruit = NULL;
    head->p_purchase = NULL;
    head->p_sell = NULL;
    head->p_account = NULL;
    head->next = NULL;
    return head;
}

//[0] fruit [1] purchaseMessage [2] sellMessage [3] account
void pointer_add(pointer *head, void *item, int type, double data) {
    pointer *p = head;
    while (p->next != NULL) p = p->next;
    p->next = (pointer *) malloc(sizeof(pointer));
    p = p->next;
    p->temp = data;
    p->p_fruit = NULL;
    p->p_purchase = NULL;
    p->p_sell = NULL;
    p->p_account = NULL;
    p->next = NULL;
    switch (type) {
        case 0:
            p->p_fruit = (fruit *) item;
            break;
        case 1:
            p->p_purchase = (purchaseMessage *) item;
            break;
        case 2:
            p->p_sell = (sellMessage *) item;
            break;
        case 3:
            p->p_account = (account *) item;
            break;
    }
}

void pointer_del(pointer *head, pointer *item) {
    pointer *p = head;
    while (p->next != item) {
        p = p->next;
    }
    p->next = item->next;
    free(item);
}

void pointer_free(pointer *head) {
    pointer *tail = head;
    while (head != NULL) {
        tail = tail->next;
        free(head);
        head = tail;
    }
}